#include "k_means.h"
#include <QTime>
#include <qmath.h>
#include <QDebug>
K_Means::K_Means()
{

}

void K_Means::setK(int K)
{
    this->K=K;
}

void K_Means::random()
{
    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
    for(int i=0;i<Count;i++){
        QVector<double> date;
        int num;
        for(int j=0;j<N;j++){

            num = qrand()%(max_date-min_date);
            //date[j]=num;
            date.append(num);
        }
        allpoint.append(date);
    }
    for(int q=0;q<allpoint.size();q++){
        qDebug()<<allpoint.at(q);
    }
}

void K_Means::K_core()
{
    QVector<QVector<double>> temp_outside;
    if(K==0){
        return;
    }
    qDebug()<<"start K point:";
    qDebug()<<Kpoint;
    int freq=0;
    while (!isEquate(temp_outside,Kpoint)) {
        //qDebug()<<"hi";
        temp_outside=Kpoint;
        point_belong.clear();
        for(int i=0;i<Count;i++){
            point_belong.insert(i,Belong(allpoint.at(i)));
        }
        Kpoint.clear();
        QVector<QVector<double>> temp_inside;
        for(int i=0;i<K;i++){
            temp_inside.clear();
            for(int j=0;j<Count;j++){
                if(i==point_belong[j]){//获取到属于同一类的点
                    //计算这同一类的点的质点然后重新给到Kpoint
                    temp_inside.append(allpoint.at(j));

                }
                //qDebug()<<temp_inside;
            }
            Kpoint.append(afresh(temp_inside));//先给到temp


        }
        //Kpoint=temp_outside;
        freq++;
        qDebug()<<"The "<<freq<<"-th result";
        qDebug()<<Kpoint;
        record_.append(Kpoint);
        for(int s=0;s<Kpoint.size();s++){
            record=record+QString::number(Kpoint.at(s).at(0))+","+QString::number(Kpoint.at(s).at(1))+",";
        }
        record=record+"\n";
    }
}

double K_Means::TwoPointDistance(QVector<double> a, QVector<double> b)
{
    double c;
    if(a.size()!=b.size()){
        return -1;
    }else{
        for(int i=0;i<a.size();i++){
            c=c+qPow(a.at(i)-b.at(i),2);
        }
        return sqrt(c);
    }
}

int K_Means::Belong(QVector<double> temp){
    double dist=INT16_MAX;
    int sub=-1;
    int square=0;

    for(int i=0;i<Kpoint.size();i++){
        square=0;
        for(int j=0;j<N;j++){
            square=square+qPow(temp.at(j)-Kpoint.at(i).at(j),2);
        }
        if(dist>sqrt(square)){
            dist=sqrt(square);
            sub=i;
        }
    }
    //qDebug()<<sub;
    return sub;
}

bool K_Means::isEquate(QVector<QVector<double> > a, QVector<QVector<double> > b)
{
    if(a.size()==0){
        return false;
    }
    for(int i=0;i<a.size();i++){
        if(!b.contains(a.at(i))){

            return false;
        }
    }
    return true;
}

bool K_Means::KMeans44()
{

    //默认以第一个点为开始的点
    if(Kpoint.size()!=0){
        Kpoint.clear();
    }
    Kpoint.append(allpoint.at(0));
    record=record+QString::number(allpoint.at(0).at(0))+","+QString::number(allpoint.at(0).at(1))+","+"\n";
    record_.append(Kpoint);
    QList<double> distance;
    for(int i=0;i<allpoint.size();i++){
        distance.append(INT_MAX);
    }
    while(Kpoint.size()<K){
        for(int i=0;i<allpoint.size();i++){
            for(int j=0;j<Kpoint.size();j++){
                double q=TwoPointDistance(allpoint.at(i),Kpoint.at(j));
                if(q<0){
                    qDebug()<<"error!";
                }
                if(distance.at(i)>q){
                    distance.replace(i,q);
                }
            }
        }
        double max_distance=0;
        int subb=-1;
        for(int r=0;r<distance.size();r++){
            if(max_distance<distance.at(r)){
                max_distance=distance.at(r);
                subb=r;
            }
        }
        qDebug()<<"add:"<<allpoint.at(subb);
        Kpoint.append(allpoint.at(subb));
        record_.append(Kpoint);
        qDebug()<<"Kpoint:"<<Kpoint;
        for(int f=0;f<Kpoint.size();f++){
            record=record+QString::number(Kpoint.at(f).at(0))+","+QString::number(Kpoint.at(f).at(1))+",";
        }
        record=record+"\n";
    }
}

QVector<double> K_Means::afresh(QVector<QVector<double> > temp)
{
    QVector<double> afresh_k_point;
    int sum=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<temp.size();j++){
            sum=sum+temp.at(j).at(i);
        }
        afresh_k_point.append(sum/temp.size());
        sum=0;
    }
    return afresh_k_point;
}




